package com.lhd.qd.config;

import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import javax.sql.DataSource;

/**
 * 事务配置
 */
@Aspect
@Configuration
public class TransactionConfig {

    private static final String EXPRESS = "execution(* com.lhd.qd.module..service.impl.*ServiceImpl.*(..))";
    private static final int TIME_OUT = 30;

    @Bean
    public DataSourceTransactionManager txManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public TransactionInterceptor txAdvice(DataSourceTransactionManager txManager) {

        RuleBasedTransactionAttribute required = new RuleBasedTransactionAttribute();
        required.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        required.setTimeout(TIME_OUT);

        RuleBasedTransactionAttribute readOnly = new RuleBasedTransactionAttribute();
        readOnly.setReadOnly(true);
        readOnly.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);

        NameMatchTransactionAttributeSource txAttributeSource = new NameMatchTransactionAttributeSource();

        txAttributeSource.addTransactionalMethod("save*", required);
        txAttributeSource.addTransactionalMethod("update*", required);
        txAttributeSource.addTransactionalMethod("remove*", required);

        txAttributeSource.addTransactionalMethod("get*", readOnly);
        txAttributeSource.addTransactionalMethod("list*", readOnly);
        txAttributeSource.addTransactionalMethod("page*", readOnly);

        return new TransactionInterceptor(txManager, txAttributeSource);
    }

    @Bean
    public Advisor txAdvisor(TransactionInterceptor txAdvice) {

        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression(EXPRESS);

        return new DefaultPointcutAdvisor(pointcut, txAdvice);
    }
}
